Fix dep_targets for tests depending on libraries
authorAlex Crichton <alex@alexcrichton.com>
Tue, 3 Mar 2015 03:17:25 +0000 (19:17 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 3 Mar 2015 03:30:57 +0000 (19:30 -0800)
Before this commit the `dep_targets` function of `Context` didn't actually
return all dependencies in the sense that unit tests (and likely examples) would
not have the same package's library listed as a dependency. This commit
rectifies the situation by ensuring that the package's library is included
whenever necessary in the dependency list.

Closes #1289

src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_freshness.rs

index e297ba40532762ea1adb6ec1a57b8eec40b35c59..409d1f761d53e8f712826f67af559e7a118e5c5d 100644 (file)
@@ -284,7 +284,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> {
             None => return vec!(),
             Some(deps) => deps,
         };
-        deps.map(|id| self.get_package(id)).filter(|dep| {
+        let mut ret = deps.map(|id| self.get_package(id)).filter(|dep| {
             let pkg_dep = pkg.dependencies().iter().find(|d| {
                 d.name() == dep.name()
             }).unwrap();
@@ -305,7 +305,24 @@ impl<'a, 'b: 'a> Context<'a, 'b> {
         }).filter_map(|pkg| {
             pkg.targets().iter().find(|&t| self.is_relevant_target(t))
                .map(|t| (pkg, t))
-        }).collect()
+        }).collect::<Vec<_>>();
+
+        // If this target is a binary, test, example, etc, then it depends on
+        // the library of the same package. The call to `resolve.deps` above
+        // didn't include `pkg` in the return values, so we need to special case
+        // it here and see if we need to push `(pkg, pkg_lib_target)`.
+        if !target.profile().is_custom_build() &&
+           (target.is_bin() || target.is_example()) {
+            let pkg = self.get_package(pkg.package_id());
+            let target = pkg.targets().iter().filter(|t| {
+                t.is_lib() && t.profile().is_compile() &&
+                    (t.is_rlib() || t.is_dylib())
+            }).next();
+            if let Some(t) = target {
+                ret.push((pkg, t));
+            }
+        }
+        return ret;
     }
 
     /// Gets a package for the given package id.
index 569fa6781ccc0585240c1642bae717ff31aa16fd..3d875ba7f0ad142ea0f2cf966ec84dd36a860eac 100644 (file)
@@ -678,17 +678,6 @@ fn build_deps_args(cmd: &mut CommandPrototype, target: &Target,
         try!(link_to(cmd, pkg, target, cx, kind));
     }
 
-    let targets = package.targets().iter().filter(|target| {
-        target.is_lib() && target.profile().is_compile()
-    });
-
-    if (target.is_bin() || target.is_example()) &&
-       !target.profile().is_custom_build() {
-        for target in targets.filter(|f| f.is_rlib() || f.is_dylib()) {
-            try!(link_to(cmd, package, target, cx, kind));
-        }
-    }
-
     return Ok(());
 
     fn link_to(cmd: &mut CommandPrototype, pkg: &Package, target: &Target,
index 394541be337ddc410186eb466a4ee04aa08793e0..24fce3aa4d40633fe364f27dc2754cb4105caacb 100644 (file)
@@ -173,3 +173,31 @@ test!(changing_features_is_ok {
                 execs().with_status(0)
                        .with_stdout(""));
 });
+
+test!(rebuild_tests_if_lib_changes {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+        "#)
+        .file("src/lib.rs", "pub fn foo() {}")
+        .file("tests/foo.rs", r#"
+            extern crate foo;
+            #[test]
+            fn test() { foo::foo(); }
+        "#);
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0));
+    assert_that(p.cargo("test"),
+                execs().with_status(0));
+
+    File::create(&p.root().join("src/lib.rs")).unwrap();
+
+    assert_that(p.cargo("build"),
+                execs().with_status(0));
+    assert_that(p.cargo("test").arg("-v"),
+                execs().with_status(101));
+});